<template>
  <!-- 素材库弹窗 -->
  <el-dialog
    :model-value="modelValue"
    @update:model-value="$emit('update:modelValue', $event)"
    title="素材库"
    width="1200px"
    top="10vh"
    destroy-on-close
    class="media-library-dialog fixed-media-dialog"
  >
    <div class="media-library">
      <!-- 左侧分组导航 -->
      <div class="media-sidebar">
        <!-- 上传按钮区域 -->
        <div class="sidebar-header">
          <el-upload
            class="media-upload"
            action="#"
            :auto-upload="false"
            :show-file-list="false"
            accept="*"
            :multiple="true"
            @change="handleFileChange"
          >
            <el-button type="primary" class="upload-btn">
              <el-icon><Upload /></el-icon>
              上传文件
            </el-button>
          </el-upload>
        </div>

        <!-- 分组菜单区域 -->
        <el-scrollbar>
          <div class="sidebar-menu">
            <!-- 文件类型过滤 -->
            <div class="menu-group">
              <div class="group-title">文件类型</div>
              <div
                v-for="type in fileTypes"
                :key="type.value"
                class="menu-item"
                :class="{ 'is-active': activeType === type.value }"
                @click="activeType = type.value"
              >
                <el-icon><component :is="type.icon" /></el-icon>
                {{ type.label }}
              </div>
            </div>

            <!-- 自定义分组 -->
            <div class="menu-group">
              <div class="group-title">
                <span>分组</span>
                <el-button link type="primary" @click="handleAddGroup">
                  <el-icon><Plus /></el-icon>
                </el-button>
              </div>
              <div
                v-for="group in mediaGroups"
                :key="group.id"
                class="menu-item"
                :class="{ 'is-active': activeGroup === group.id }"
                @click="handleGroupClick(group.id)"
              >
                <el-icon><Folder /></el-icon>
                {{ group.name }}
              </div>
            </div>
          </div>
        </el-scrollbar>
      </div>

      <!-- 右侧内容区 -->
      <div class="media-main">
        <!-- 顶部操作栏 -->
        <div class="main-header">
          <div class="header-left">
            <!-- 视图切换 -->
            <el-radio-group v-model="viewMode" size="default">
              <el-radio-button :value="'grid'">
                <el-icon><Grid /></el-icon>
              </el-radio-button>
              <el-radio-button :value="'list'">
                <el-icon><List /></el-icon>
              </el-radio-button>
            </el-radio-group>
          </div>

          <!-- 批量操作区域 -->
          <div class="batch-actions" v-if="viewMode === 'list' && selectedItems.length > 0">
            <div class="selected-info">
              <span class="selected-count">已选择 {{ selectedItems.length }} 个文件</span>
            </div>
            <div class="action-buttons">
              <el-button type="primary" @click="handleBatchInsert">
                <el-icon><DocumentAdd /></el-icon>
                <span>插入</span>
              </el-button>
              <el-button type="danger" @click="handleBatchDelete">
                <el-icon><Delete /></el-icon>
                <span>删除</span>
              </el-button>
            </div>
          </div>

          <!-- 搜索和排序 -->
          <div class="header-right" v-else>
            <el-input v-model="searchKeyword" placeholder="搜索文件" class="search-input" clearable>
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>

            <el-select v-model="sortField" placeholder="排序字段" size="default">
              <el-option label="按名称" value="name" />
              <el-option label="按时间" value="updateOn" />
              <el-option label="按大小" value="fileSize" />
            </el-select>
            <el-select v-model="sortOrder" placeholder="排序顺序" size="default">
              <el-option label="升序" value="ascend" />
              <el-option label="降序" value="descend" />
            </el-select>
          </div>
        </div>

        <!-- 内容区域 -->
        <div class="main-content">
          <el-scrollbar>
            <!-- 网格视图 -->
            <template v-if="viewMode === 'grid'">
              <div class="media-grid">
                <div
                  v-for="item in currentPageData"
                  :key="item.id"
                  class="media-item"
                  @click="handleItemClick(item)"
                >
                  <!-- 操作按钮 -->
                  <div class="item-actions">
                    <el-tooltip content="复制" placement="top">
                      <el-button
                        class="action-btn copy-btn"
                        link
                        @click.stop="handleCopyLink(item)"
                      >
                        <el-icon><Link /></el-icon>
                      </el-button>
                    </el-tooltip>
                    <el-tooltip content="删除" placement="top">
                      <el-button
                        class="action-btn delete-btn"
                        link
                        @click.stop="handleDeleteMedia(item)"
                      >
                        <el-icon><Delete /></el-icon>
                      </el-button>
                    </el-tooltip>
                  </div>

                  <!-- 预览区域 -->
                  <div class="item-preview">
                    <!-- 图片类型 -->
                    <template v-if="item.type === 'image'">
                      <el-image :src="item.url" fit="cover" :preview-src-list="[]">
                        <template #error>
                          <div class="image-error">
                            <el-icon><Picture /></el-icon>
                          </div>
                        </template>
                      </el-image>
                    </template>
                    <!-- 非图片类型 -->
                    <template v-else>
                      <div class="file-preview" :class="getFileTypeClass(item)">
                        <div class="file-icon">
                          <el-icon>
                            <Document v-if="item.type === 'document'" />
                            <Files v-else />
                          </el-icon>
                          <span class="file-ext">{{ getFileExtension(item.name) }}</span>
                        </div>
                      </div>
                    </template>
                  </div>

                  <!-- 信息区域 -->
                  <div class="item-info">
                    <div class="info-main">
                      <div class="file-name">{{ item.name }}</div>
                    </div>
                    <div class="info-detail">
                      <span class="size">{{ item.size }}</span>
                      <span class="time">{{ formatTime(item.updateTime) }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </template>

            <!-- 列表视图 -->
            <template v-else>
              <div class="media-list">
                <el-table
                  :data="currentPageData"
                  style="width: 100%; height: 100%"
                  height="100%"
                  @selection-change="handleSelectionChange"
                >
                  <el-table-column type="selection" width="55" align="center" />
                  <el-table-column
                    label="文件名"
                    min-width="180"
                    show-overflow-tooltip
                    align="left"
                  >
                    <template #default="{ row }">
                      <div class="file-cell">
                        <!-- 图片类型 -->
                        <template v-if="row.type === 'image'">
                          <div class="file-type-icon">
                            <el-image
                              :src="row.url"
                              class="file-thumbnail"
                              fit="cover"
                              :preview-src-list="[row.url]"
                              preview-teleported
                              :initial-index="0"
                              :hide-on-click-modal="false"
                            >
                              <template #error>
                                <div class="image-placeholder">
                                  <el-icon><Picture /></el-icon>
                                </div>
                              </template>
                            </el-image>
                            <!-- 添加预览图标 -->
                            <div class="preview-icon">
                              <el-icon><ZoomIn /></el-icon>
                            </div>
                          </div>
                        </template>
                        <!-- 文档类型 -->
                        <template v-else>
                          <div class="file-type-icon" :class="getFileTypeClass(row)">
                            <div class="file-type-bg">
                              <el-icon>
                                <Document v-if="row.type === 'document'" />
                                <Files v-else />
                              </el-icon>
                            </div>
                            <div class="file-type-label">
                              {{ getFileExtension(row.name) }}
                            </div>
                          </div>
                        </template>
                        <span class="file-name" :title="row.name">{{ row.name }}</span>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="类型" width="100" align="center">
                    <template #default="{ row }">
                      <el-tag
                        :type="
                          row.type === 'image'
                            ? 'success'
                            : row.type === 'document'
                              ? 'info'
                              : 'warning'
                        "
                        size="small"
                      >
                        {{
                          row.type === 'image' ? '图片' : row.type === 'document' ? '文档' : '其他'
                        }}
                      </el-tag>
                    </template>
                  </el-table-column>
                  <el-table-column prop="size" label="大小" width="100" align="center" />
                  <el-table-column label="修改时间" width="180" align="center">
                    <template #default="{ row }">
                      {{ formatTime(row.updateTime) }}
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="操作"
                    width="220"
                    fixed="right"
                    class-name="operation-cell"
                  >
                    <template #default="{ row }">
                      <div class="operation-buttons">
                        <el-button
                          link
                          type="primary"
                          size="small"
                          @click.stop="handleSelectMedia(row)"
                        >
                          <el-icon><DocumentAdd /></el-icon>使用
                        </el-button>
                        <el-button
                          link
                          type="primary"
                          size="small"
                          @click.stop="handleCopyLink(row)"
                        >
                          <el-icon><Link /></el-icon>复制
                        </el-button>
                        <el-button
                          link
                          type="danger"
                          size="small"
                          @click.stop="handleDeleteMedia(row)"
                        >
                          <el-icon><Delete /></el-icon>删除
                        </el-button>
                      </div>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </template>
          </el-scrollbar>

          <!-- 分页器 -->
          <div class="pagination-wrapper">
            <el-pagination
              v-model:current-page="currentPage"
              v-model:page-size="pageSize"
              :total="totalCount"
              :page-sizes="[12, 24, 36, 48]"
              layout="total, sizes, prev, pager, next, jumper"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
            />
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup>
/**
 * @component MediaLibrary
 * @description 素材库组件，用于管理和选择媒体资源
 *
 * 功能：
 * - 支持网格/列表两种查看方式
 * - 支持按类型、分组筛选媒体文件
 * - 支持搜索和排序
 * - 支持单选和批量选择插入
 * - 支持复制 Markdown 格式的链接
 * - 支持删除文件操作
 */

import { ref, computed, watch, onMounted } from 'vue'
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import {
  Search,
  Delete,
  Files,
  Plus,
  Folder,
  Document,
  Link,
  Grid,
  List,
  ZoomIn,
  Picture,
  DocumentAdd,
  Upload,
} from '@element-plus/icons-vue'

// 导入API
import { sourceApi } from '@/api/source'

// =============== Props & Emits 定义 ===============

/**
 * Props 定义
 * @property {Boolean} modelValue - 控制组件的显示/隐藏
 */
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
})

/**
 * 事件定义
 * @event update:modelValue - 更新显示/隐藏状态
 * @event select-media - 选择单个媒体项时触发
 * @event batch-insert - 批量插入媒体项时触发
 */
const emit = defineEmits(['update:modelValue', 'select-media', 'batch-insert'])

// =============== 状态定义 ===============

/**
 * 基础状态
 */
const searchKeyword = ref('') // 搜索关键词
const activeType = ref('all') // 当前选中的文件类型过滤
const activeGroup = ref(null) // 当前选中的分组
const viewMode = ref('grid') // 当前视图模式：grid/list
const sortField = ref('updateOn') // 当前排序字段
const sortOrder = ref('ascend') // 当前排序顺序
const selectedItems = ref([]) // 已选中的项（用于批量操作）
const currentPage = ref(1) // 当前页码
const pageSize = ref(12) // 每页展示数量
const totalCount = ref(0) // 总文件数量

/**
 * 文件类型配置
 * @type {Array<{value: string, label: string, icon: Component}>}
 */
const fileTypes = [
  { value: 'all', label: '全部文件', icon: Files },
  { value: 'image', label: '图片', icon: Picture },
  { value: 'document', label: '文档', icon: Document },
  { value: 'other', label: '其他', icon: Files },
]

/**
 * 分组数据
 * @type {Array<{id: string, name: string, description: string}>}
 */
const mediaGroups = ref([{ id: '-1', name: '未分组', description: '默认分组，未分类的文件' }])

/**
 * 媒体文件数据
 * @type {Array<{id: number, name: string, type: string, url: string, size: string, updateTime: string, groupId: string}>}
 */
const mediaList = ref([])

// =============== 计算属性 ===============

/**
 * 过滤后的媒体列表
 * @returns {Array} 应用过滤条件后的媒体列表
 */
const filteredMediaList = computed(() => {
  // 已经在API请求中应用了过滤，直接返回结果
  return mediaList.value
})

/**
 * 当前页数据
 * @returns {Array} 当前页需显示的数据列表
 */
const currentPageData = computed(() => {
  // 分页已在API层处理，可以直接返回结果
  return mediaList.value
})

// =============== 工具方法 ===============

/**
 * 获取文件扩展名
 * @param {string} filename - 文件名
 * @returns {string} 大写的文件扩展名
 */
const getFileExtension = (filename) => filename.split('.').pop().toUpperCase()

/**
 * 获取文件类型样式类
 * @param {Object} file - 文件对象
 * @returns {Object} 包含对应文件类型CSS类的对象
 */
const getFileTypeClass = (file) => {
  const ext = getFileExtension(file.name).toLowerCase()
  return {
    'file-type-doc': ['doc', 'docx'].includes(ext),
    'file-type-pdf': ext === 'pdf',
    'file-type-txt': ext === 'txt',
    'file-type-excel': ['xls', 'xlsx'].includes(ext),
    'file-type-ppt': ['ppt', 'pptx'].includes(ext),
    'file-type-zip': ['zip', 'rar', '7z', 'tar', 'gz'].includes(ext),
    'file-type-code': ['js', 'ts', 'html', 'css', 'java', 'py', 'php', 'c', 'cpp', 'cs'].includes(
      ext,
    ),
    'file-type-other': ![
      'doc',
      'docx',
      'pdf',
      'txt',
      'xls',
      'xlsx',
      'ppt',
      'pptx',
      'zip',
      'rar',
      '7z',
      'tar',
      'gz',
      'js',
      'ts',
      'html',
      'css',
      'java',
      'py',
      'php',
      'c',
      'cpp',
      'cs',
    ].includes(ext),
  }
}

/**
 * 格式化时间为易读形式
 * @param {string} time - 时间字符串
 * @returns {string} 格式化后的时间字符串 YYYY/MM/DD HH:MM
 */
const formatTime = (time) => {
  const date = new Date(time)
  const pad = (num) => String(num).padStart(2, '0')

  const year = date.getFullYear()
  const month = pad(date.getMonth() + 1)
  const day = pad(date.getDate())
  const hours = pad(date.getHours())
  const minutes = pad(date.getMinutes())

  return `${year}/${month}/${day} ${hours}:${minutes}`
}

// =============== 事件处理方法 ===============

/**
 * 页面大小变化处理
 * @param {number} val - 新的每页展示数量
 */
const handleSizeChange = (val) => {
  pageSize.value = val
  currentPage.value = 1 // 重置到第一页
  loadMediaList() // 重新加载数据
}

/**
 * 当前页变化处理
 * @param {number} val - 新的页码
 */
const handleCurrentChange = (val) => {
  currentPage.value = val
  loadMediaList() // 重新加载数据
}

/**
 * 表格选择变化处理
 * @param {Array} selection - 选中的项目列表
 */
const handleSelectionChange = (selection) => {
  selectedItems.value = selection
}

/**
 * 分组点击逻辑，支持取消选中
 * @param {string} groupId - 分组ID
 */
const handleGroupClick = (groupId) => {
  // 如果当前已选中该分组，则取消选中
  if (activeGroup.value === groupId) {
    activeGroup.value = null
  } else {
    // 否则选中该分组
    activeGroup.value = groupId
  }
}

/**
 * 处理文件上传
 * @param {Object} file - 上传的文件对象
 */
const handleFileChange = async ({ raw, name }) => {
  if (!raw) {
    ElMessage.error('无效的文件')
    return
  }

  try {
    const loading = ElLoading.service({
      lock: true,
      text: '上传中...',
      background: 'rgba(0, 0, 0, 0.7)',
    })

    // 确定上传的分组ID，默认为当前选中的分组，如果没有选中则为"未分组"
    const targetGroupId = activeGroup.value !== null ? activeGroup.value : '-1'

    // 调用上传API
    await sourceApi.uploadSource(raw, targetGroupId)

    // 刷新媒体列表
    await loadMediaList()

    ElMessage.success(`文件 ${name} 上传成功`)
  } catch (error) {
    console.error('上传失败:', error)
    ElMessage.error(`文件 ${name} 上传失败，请重试`)
  } finally {
    loading.close()
  }
}

/**
 * 删除媒体文件
 * @param {Object} item - 要删除的媒体项
 */
const handleDeleteMedia = async (item) => {
  try {
    await ElMessageBox.confirm('确定要删除这个文件吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })

    // 调用API删除文件
    await sourceApi.deleteSource(item.id)

    // 刷新列表
    await loadMediaList()

    ElMessage.success('删除成功')
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除失败:', error)
      ElMessage.error('删除失败，请重试')
    }
  }
}

/**
 * 添加分组
 */
const handleAddGroup = async () => {
  try {
    // 使用弹窗输入新分组名称
    const { value: groupName } = await ElMessageBox.prompt('请输入分组名称', '新建分组', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      inputPattern: /^.{1,20}$/,
      inputErrorMessage: '分组名称不能为空且长度不超过20个字符',
    })

    if (!groupName) return

    // 调用API创建分组
    await sourceApi.createGroup(groupName, '')

    // 刷新分组列表
    await loadGroups()

    ElMessage.success('分组创建成功')
  } catch (error) {
    if (error !== 'cancel') {
      console.error('创建分组失败:', error)
      ElMessage.error('创建分组失败，请重试')
    }
  }
}

/**
 * 复制媒体链接为Markdown格式
 * @param {Object} item - 媒体项
 */
const handleCopyLink = async (item) => {
  try {
    // 根据文件类型生成不同的 markdown 语法
    const markdown =
      item.type === 'image'
        ? `![${item.name}](${item.url})` // 图片格式
        : `[${item.name}](${item.url})` // 链接格式

    // 复制到剪贴板
    await navigator.clipboard.writeText(markdown)
    ElMessage.success('链接已复制到剪贴板')
  } catch (error) {
    console.error('复制失败:', error)
    ElMessage.error('复制失败，请手动复制')
  }
}

/**
 * 处理项目点击
 * @param {Object} item - 点击的媒体项
 */
const handleItemClick = (item) => {
  // 在网格视图中点击项目时直接选择使用该项
  if (viewMode.value === 'grid') {
    handleSelectMedia(item)
  }
}

/**
 * 选择媒体项，将其数据发送给父组件
 * @param {Object} item - 选中的媒体项
 */
const handleSelectMedia = (item) => {
  // 触发选择事件，将选中的媒体项传递给父组件
  emit('select-media', item)
  // 关闭媒体库对话框
  emit('update:modelValue', false)
}

/**
 * 批量插入已选择的媒体项
 */
const handleBatchInsert = () => {
  // 验证是否有选择的项目
  if (selectedItems.value.length === 0) {
    ElMessage.warning('请先选择媒体文件')
    return
  }

  // 触发批量插入事件，将选中的媒体项传递给父组件
  emit('batch-insert', selectedItems.value)
  // 关闭媒体库对话框
  emit('update:modelValue', false)
  // 清空选择
  selectedItems.value = []
}

/**
 * 批量删除已选择的媒体项
 */
const handleBatchDelete = async () => {
  try {
    await ElMessageBox.confirm(
      `确定要删除选中的 ${selectedItems.value.length} 个文件吗？`,
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )

    // 获取所有选中项的ID
    const ids = selectedItems.value.map((item) => item.id)

    // 调用API批量删除
    await sourceApi.deleteSource(ids)

    // 刷新列表
    await loadMediaList()

    // 清空选择
    selectedItems.value = []
    ElMessage.success('删除成功')
  } catch (error) {
    if (error !== 'cancel') {
      console.error('批量删除失败:', error)
      ElMessage.error('批量删除失败，请重试')
    }
  }
}

/**
 * 加载媒体列表
 */
const loadMediaList = async () => {
  try {
    const loading = ElLoading.service({
      lock: true,
      text: '加载中...',
      background: 'rgba(0, 0, 0, 0.5)',
    })
    const params = {
      pageNum: currentPage.value,
      pageSize: pageSize.value,
      name: searchKeyword.value || undefined, // 搜索关键词
      fileType: activeType.value === 'all' ? undefined : mapTypeToFileType(activeType.value),
      groupId: activeGroup.value !== null ? String(activeGroup.value) : undefined,
      sortField: sortField.value,
      sortOrder: sortOrder.value,
    }
    const res = await sourceApi.getList(params)
    if (res && res.records) {
      mediaList.value = res.records.map((item) => ({
        id: item.id,
        name: item.name || '未命名文件',
        type: getTypeDisplayFromCode(item.fileType),
        url: item.url || '#',
        size: item.fileSize ? formatFileSize(item.fileSize) : '0 B',
        updateTime: item.updateOn || item.createOn || new Date().toISOString(),
        groupId: item.groupId === null || item.groupId === undefined ? '-1' : String(item.groupId),
      }))
      totalCount.value = res.total || 0
    } else {
      mediaList.value = []
      totalCount.value = 0
    }
    loading.close()
  } catch (error) {
    console.error('加载素材列表失败:', error)
    ElMessage.error('加载素材列表失败')
    mediaList.value = []
    totalCount.value = 0
  }
}

/**
 * 加载分组列表
 */
const loadGroups = async () => {
  try {
    const res = await sourceApi.getGroups()
    if (res && Array.isArray(res)) {
      // 确保有未分组选项
      const hasUngrouped = res.some((group) => String(group.id) === '-1')

      // 处理分组数据，确保id是字符串类型
      const processedGroups = res.map((group) => ({
        ...group,
        id: String(group.id),
      }))

      if (!hasUngrouped) {
        // 添加未分组选项
        processedGroups.unshift({
          id: '-1',
          name: '未分组',
          description: '默认分组，未分类的文件',
        })
      }

      mediaGroups.value = processedGroups
    }
  } catch (error) {
    console.error('加载分组失败:', error)
    ElMessage.error('加载分组失败')
    // 保持默认的未分组选项
    mediaGroups.value = [{ id: '-1', name: '未分组', description: '默认分组，未分类的文件' }]
  }
}

/**
 * 加载所有数据
 */
const loadData = async () => {
  // 先加载分组
  await loadGroups()
  // 然后加载媒体列表
  await loadMediaList()
}

/**
 * 将前端类型映射为后端fileType
 * @param {string} type 前端类型 'image', 'document'
 * @returns {string} 后端fileType '0', '1', '2'
 */
const mapTypeToFileType = (type) => {
  switch (type) {
    case 'image':
      return '0'
    case 'document':
      return '1'
    case 'other':
      return '2'
    default:
      return null
  }
}

/**
 * 根据类型编码获取显示类型
 * @param {string|number} typeCode 类型编码 '0'-图片, '1'-文档, '2'-其他
 * @returns {string} 显示类型 'image', 'document', 'other'
 */
const getTypeDisplayFromCode = (typeCode) => {
  switch (String(typeCode)) {
    case '0':
      return 'image'
    case '1':
      return 'document'
    case '2':
      return 'other' // 使用other作为其他文件的显示类型
    default:
      return 'document'
  }
}

/**
 * 格式化文件大小
 * @param {number} size 文件大小（字节）
 * @returns {string} 格式化后的大小
 */
const formatFileSize = (size) => {
  if (!size) return '0 B'

  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let i = 0
  let parsedSize = parseFloat(size)

  while (parsedSize >= 1024 && i < units.length - 1) {
    parsedSize /= 1024
    i++
  }

  return `${parsedSize.toFixed(1)} ${units[i]}`
}

// =============== 监听器 ===============
// 注意：确保所有引用的方法在这些监听器之前定义

/**
 * 监听对话框显示状态，显示时加载数据
 */
watch(
  () => props.modelValue,
  (newValue) => {
    if (newValue) {
      // 对话框打开时加载最新数据
      // 重置一些状态
      activeType.value = 'all'
      activeGroup.value = null // 初始化为null，表示不选中任何分组
      sortField.value = 'updateOn'
      sortOrder.value = 'ascend'
      searchKeyword.value = ''
      currentPage.value = 1
      pageSize.value = 12
      selectedItems.value = []
      // 加载数据
      loadData()
    }
  },
)

/**
 * 监听筛选条件变化，刷新媒体列表
 */
watch(
  [activeType, activeGroup, sortField, sortOrder, searchKeyword],
  () => {
    // 只有在对话框打开时才重新加载数据
    if (props.modelValue) {
      // 重置页码并重新加载数据
      currentPage.value = 1
      loadMediaList()
    }
  },
  { deep: true },
)

/**
 * 组件挂载时加载数据
 */
onMounted(() => {
  // 如果对话框是打开状态，则加载数据
  if (props.modelValue) {
    loadData()
  }
})
</script>

<style lang="scss" scoped>
@use 'sass:color';

// 固定高度弹窗样式
:deep(.fixed-media-dialog) {
  .el-dialog {
    height: 80vh !important;
    max-height: 80vh !important;
    min-height: 80vh !important;
    display: flex;
    flex-direction: column;
  }
  .el-dialog__body {
    flex: 1 1 auto;
    height: 100% !important;
    min-height: 0;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
}

// 素材库主容器
.media-library {
  height: 100%;
  min-height: 0;
  display: flex;

  // =============== 左侧边栏样式 ===============
  .media-sidebar {
    width: 220px;
    border-right: 1px solid $border-base;
    display: flex;
    flex-direction: column;

    // 上传按钮区域
    .sidebar-header {
      padding: 10px;
      border-bottom: 1px solid $border-base;

      .upload-btn {
        width: 100%;
      }
    }

    // 分组菜单区域
    .sidebar-menu {
      padding: 16px 0;

      // 菜单组样式
      .menu-group {
        & + .menu-group {
          margin-top: 24px; // 组间距
        }

        // 组标题
        .group-title {
          padding: 0 16px 8px;
          font-size: $font-size-small;
          color: $text-secondary;
          @include flex-between;
        }

        // 菜单项
        .menu-item {
          padding: 8px 16px;
          @include flex-center;
          justify-content: flex-start;
          gap: 8px;
          color: $text-regular;
          cursor: pointer;
          transition: $transition-base;

          &:hover {
            color: $primary-color;
            background-color: color.mix($primary-color, $bg-base, $weight: 4%);
          }

          &.is-active {
            color: $primary-color;
            background-color: color.mix($primary-color, $bg-base, $weight: 8%);
          }

          .el-icon {
            font-size: 16px;
          }
        }
      }
    }
  }

  // =============== 右侧主内容区样式 ===============
  .media-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    height: 100%;

    // 顶部操作栏
    .main-header {
      padding: 6px;
      border-bottom: 1px solid $border-base;
      @include flex-between;

      // 左侧视图切换
      .header-left {
        display: flex;
        gap: 12px;
        align-items: center;
      }

      // 批量操作区域
      .batch-actions {
        display: flex;
        align-items: center;
        gap: 16px;
        animation: fadeIn 0.3s ease;

        // 选中数量提示
        .selected-info {
          .selected-count {
            font-size: 14px;
            color: $text-regular;
            background-color: color.mix($primary-color, $bg-base, $weight: 8%);
            padding: 4px 12px;
            border-radius: 12px;
            font-weight: 500;
          }
        }

        // 操作按钮组
        .action-buttons {
          display: flex;
          gap: 8px;

          .el-button {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            padding: 8px 16px;
            font-weight: 500;

            .el-icon {
              font-size: 16px;
            }
          }
        }
      }

      // 搜索和排序区域
      .header-right {
        display: flex;
        gap: 12px;
        align-items: center;
      }
    }

    // 主内容区域
    .main-content {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 0;
      overflow: hidden;
      height: 0;

      .el-scrollbar {
        flex: 1;
        min-height: 0;
        height: 0;
        max-height: 100%;
      }

      // 分页器
      .pagination-wrapper {
        height: 64px;
        padding: 0 16px;
        border-top: 1px solid $border-light;
        @include flex-center;
        flex-shrink: 0; // 防止分页器被压缩
      }
    }
  }

  // =============== 网格视图样式 ===============
  .media-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    padding: 20px;
    align-content: flex-start;

    // 网格项
    .media-item {
      width: calc((100% - 80px) / 5); // 5列布局
      aspect-ratio: 4/3;
      margin-bottom: 16px;
      position: relative;
      border: 1px solid $border-base;
      border-radius: $border-radius-medium;
      overflow: hidden;
      transition: all 0.3s ease;
      background: $bg-base;
      cursor: pointer;

      // 操作按钮
      .item-actions {
        position: absolute;
        top: 8px;
        left: 8px;
        right: 8px;
        display: flex;
        justify-content: space-between;
        z-index: 2;
        opacity: 0;
        transform: translateY(-10px);
        transition: all 0.3s ease;

        .action-btn {
          width: 32px;
          height: 32px;
          border-radius: 50%;
          background: rgba($bg-base, 0.9);
          backdrop-filter: blur(4px);
          @include flex-center;
          transition: all 0.3s ease;

          .el-icon {
            font-size: 16px;
          }

          &.copy-btn:hover {
            color: $primary-color;
            background: rgba($bg-base, 0.95);
          }

          &.delete-btn:hover {
            color: $danger-color;
            background: rgba($bg-base, 0.95);
          }
        }
      }

      // 预览区域
      .item-preview {
        position: absolute;
        inset: 0;
        transition: all 0.3s ease;

        .el-image {
          width: 100%;
          height: 100%;

          :deep(img) {
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: transform 0.3s ease;
          }
        }

        // 文档预览样式
        .file-preview {
          width: 100%;
          height: 100%;
          @include flex-center;
          background: linear-gradient(
            45deg,
            rgba($primary-color, 0.02),
            rgba($primary-color, 0.06)
          );

          .file-icon {
            @include flex-center;
            flex-direction: column;
            gap: 8px;

            .el-icon {
              font-size: 40px;
              transition: transform 0.3s ease;
            }

            .file-ext {
              font-size: 12px;
              padding: 3px 10px;
              border-radius: 12px;
              background: rgba($primary-color, 0.08);
              color: $text-regular;
              font-weight: 500;
            }
          }
        }
      }

      // 信息区域
      .item-info {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        padding: 8px 12px;
        background: rgba($bg-base, 0.85);
        backdrop-filter: blur(4px);
        transform: translateY(100%);
        transition: all 0.3s ease;

        .info-main {
          .file-name {
            @include text-ellipsis;
            font-size: 13px;
            color: $text-primary;
            font-weight: 500;
          }
        }

        .info-detail {
          margin-top: 4px;
          display: flex;
          align-items: center;
          gap: 8px;
          font-size: 12px;

          .size {
            padding: 2px 8px;
            background: rgba($primary-color, 0.1);
            border-radius: 10px;
            color: $primary-color;
          }

          .time {
            color: $text-secondary;
          }
        }
      }

      // 悬浮效果
      &:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 24px rgba($primary-color, 0.12);
        border-color: $primary-color;

        .item-preview {
          .el-image :deep(img) {
            transform: scale(1.05);
          }

          .file-preview .file-icon .el-icon {
            transform: scale(1.1);
          }
        }

        .item-info {
          transform: translateY(0);
        }

        .item-actions {
          opacity: 1;
          transform: translateY(0);
        }
      }
    }
  }

  // =============== 列表视图样式 ===============
  .media-list {
    height: 100%;
    min-height: 0;
    display: flex;
    flex-direction: column;

    .el-table--fit {
      flex: 1;

      // 文件单元格样式
      .file-cell {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 8px;
        justify-content: flex-start;

        // 文件类型图标
        .file-type-icon {
          width: 48px;
          height: 48px;
          flex-shrink: 0;
          position: relative;
          border-radius: 6px;
          overflow: hidden;
          border: 1px solid $border-light;
          background: $bg-light;
          cursor: pointer;

          // 缩略图
          .file-thumbnail {
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
          }

          // 文档类型样式
          &.file-type-pdf {
            .file-type-bg {
              background: linear-gradient(45deg, #ffebee, #ffcdd2);
              color: #d32f2f;
            }
            .file-type-label {
              background-color: #ef5350;
            }
          }

          &.file-type-doc {
            .file-type-bg {
              background: linear-gradient(45deg, #e3f2fd, #bbdefb);
              color: #1976d2;
            }
            .file-type-label {
              background-color: #42a5f5;
            }
          }

          &.file-type-excel {
            .file-type-bg {
              background: linear-gradient(45deg, #e8f5e9, #c8e6c9);
              color: #2e7d32;
            }
            .file-type-label {
              background-color: #66bb6a;
            }
          }

          &.file-type-ppt {
            .file-type-bg {
              background: linear-gradient(45deg, #fff3e0, #ffe0b2);
              color: #e65100;
            }
            .file-type-label {
              background-color: #ff9800;
            }
          }

          &.file-type-zip {
            .file-type-bg {
              background: linear-gradient(45deg, #f3e5f5, #e1bee7);
              color: #7b1fa2;
            }
            .file-type-label {
              background-color: #ab47bc;
            }
          }

          &.file-type-code {
            .file-type-bg {
              background: linear-gradient(45deg, #e0f7fa, #b2ebf2);
              color: #0097a7;
            }
            .file-type-label {
              background-color: #26c6da;
            }
          }

          &.file-type-txt {
            .file-type-bg {
              background: linear-gradient(45deg, #fafafa, #f5f5f5);
              color: #616161;
            }
            .file-type-label {
              background-color: #9e9e9e;
            }
          }

          &.file-type-other {
            .file-type-bg {
              background: linear-gradient(45deg, #fffde7, #fff9c4);
              color: #afb42b;
            }
            .file-type-label {
              background-color: #d4e157;
            }
          }

          // 文件类型背景
          .file-type-bg {
            width: 100%;
            height: 100%;
            @include flex-center;

            .el-icon {
              font-size: 20px;
            }
          }

          // 文件类型标签
          .file-type-label {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            height: 16px;
            @include flex-center;
            color: #fff;
            font-size: 10px;
            font-weight: 500;
          }

          // 预览图标
          .preview-icon {
            position: absolute;
            inset: 0;
            background: rgba($primary-color, 0.2);
            backdrop-filter: blur(2px);
            @include flex-center;
            opacity: 0;
            transform: translateY(5px);
            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
            pointer-events: none;

            .el-icon {
              font-size: 24px;
              color: #fff;
              filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
            }
          }

          // 悬浮效果
          &:hover {
            border-color: $primary-color;
            box-shadow: 0 2px 8px rgba($primary-color, 0.15);

            .preview-icon {
              opacity: 1;
              transform: translateY(0);
            }

            .file-thumbnail {
              transform: scale(1.08);
            }
          }

          // 非图片类型处理
          &:not(:has(.file-thumbnail)) {
            cursor: default;

            .preview-icon {
              display: none;
            }

            &:hover {
              border-color: $border-light;
              box-shadow: none;
              transform: none;
            }
          }

          // 点击效果
          &:active {
            .file-thumbnail {
              transform: scale(1);
            }

            .preview-icon {
              background: rgba($primary-color, 0.25);
            }
          }
        }

        // 文件名
        .file-name {
          flex: 1;
          min-width: 0;
          @include text-ellipsis;
          cursor: default;
          text-align: left;
        }
      }
    }

    // 操作列样式
    .operation-cell {
      .cell {
        padding: 0 8px;

        .operation-buttons {
          display: flex;
          align-items: center;
          justify-content: center;

          .el-button {
            height: 28px;
            padding: 0 8px;
            font-size: 12px;

            &.el-button--text {
              margin: 0;

              .el-icon {
                font-size: 14px;
              }
            }

            :deep(.el-button__content) {
              display: inline-flex;
              align-items: center;
              gap: 4px;
            }

            // 按钮分隔线
            &:not(:last-child)::after {
              content: '';
              position: absolute;
              right: -4px;
              top: 50%;
              transform: translateY(-50%);
              width: 1px;
              height: 12px;
              background-color: $border-light;
            }
          }
        }
      }
    }

    // 表格单元格对齐
    :deep(.el-table__cell) {
      .cell {
        display: flex;
        align-items: center;
        justify-content: center;
      }

      // 文件名列左对齐
      &:nth-child(2) .cell {
        justify-content: flex-start;
      }
    }
  }
}

// 淡入动画
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
